package cn.edu.lsnu.mbti.service.impl;


import cn.edu.lsnu.mbti.common.Constants;
import cn.edu.lsnu.mbti.dto.MajorDto;
import cn.edu.lsnu.mbti.entity.Category;
import cn.edu.lsnu.mbti.entity.Department;
import cn.edu.lsnu.mbti.entity.Major;
import cn.edu.lsnu.mbti.entity.vo.MajorVo;
import cn.edu.lsnu.mbti.exception.CustomerException;
import cn.edu.lsnu.mbti.mapper.MajorMapper;
import cn.edu.lsnu.mbti.service.CategoryService;
import cn.edu.lsnu.mbti.service.DepartmentService;
import cn.edu.lsnu.mbti.service.MajorService;
import cn.edu.lsnu.mbti.util.RedisUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MajorServiceImpl extends ServiceImpl<MajorMapper, Major> implements MajorService {

    public static final String majorKey = "MBTI:MAJOR:ALL";
    public static final String majorCategoryKey = "MBTI:MAJOR:";
    @Resource
    private RedisUtil redisUtil;
    @Resource
    @Lazy
    private DepartmentService departmentService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private MajorMapper majorMapper;


    /**
     * vue后台管理保存专业
     * @param major
     * @return
     */
    @Override
    @Transactional
    public String saveMajor(Major major) {
        try {
            int result = 0;
            //判断id是否为空
            if (StrUtil.isBlank(major.getId())){
                //空，新增院校
                result = majorMapper.insert(major);
            }else{
                //不为空，修改用户
                result = majorMapper.updateById(major);
            }
            if (result > 0){
                return "保存成功";
            }
        } catch (Exception e) {
            throw new CustomerException("保存失败，请稍后重试");
        }
        throw new CustomerException("保存失败，请稍后重试");
    }

    /**
     * vue后台管理分页查询专业集合
     * @param majorVo
     * @return
     */
    @Override
    public Page<MajorDto> queryPageMajorList(MajorVo majorVo) {
        //构造查询条件
        LambdaQueryWrapper<Major> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Major::getName,majorVo.getName());
        wrapper.eq(StrUtil.isNotBlank(majorVo.getDepartmentId()),Major::getDepartmentId,majorVo.getDepartmentId());
        wrapper.eq(StrUtil.isNotBlank(majorVo.getCategoryId()),Major::getCategoryId,majorVo.getCategoryId());
        wrapper.orderByDesc(Major::getCreateTime);
        Page<Major> majorPage = new Page<>(majorVo.getPageNum(), majorVo.getPageSize());

        //分页查询
        majorPage = this.page(majorPage,wrapper);

        //对象复制
        Page<MajorDto> majorDtoPage = new Page<>();
        BeanUtils.copyProperties(majorPage,majorDtoPage,"records");

        //封装属性
        majorDtoPage.setRecords(majorPage.getRecords().stream().map(major -> {
            MajorDto majorDto = new MajorDto();
            BeanUtils.copyProperties(major,majorDto);
            if (StrUtil.isNotBlank(major.getDepartmentId())){
                Department department = departmentService.getById(major.getDepartmentId());
                if (BeanUtil.isNotEmpty(department)){
                    majorDto.setDepartmentName(department.getName());
                }
            }
            if (StrUtil.isNotBlank(major.getCategoryId())){
                Category category = categoryService.getById(major.getCategoryId());
                if (BeanUtil.isNotEmpty(category)){
                    majorDto.setCategoryName(category.getName());
                }
            }

            return majorDto;
        }).collect(Collectors.toList()));

        return majorDtoPage;
    }

    /**
     * 根据不同的分类id查询不同的硕士专业
     * @param categoryId
     * @return
     */
    @Override
    public List<MajorDto> queryListByCategoryId(String categoryId) {
        //查询redis
        String jsonStr = (String) redisUtil.get(majorCategoryKey);

        //判断redis中的是否存在
        if (StrUtil.isNotBlank(jsonStr)){
            //转化为对象
            List<MajorDto> majorDtoList = JSONUtil.toBean(jsonStr, new TypeReference<List<MajorDto>>() {
            }, true);
            return majorDtoList;
        }

        //查询专业集合
        LambdaQueryWrapper<Major> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(categoryId),Major::getCategoryId,categoryId);
        List<Major> majorList = this.list(queryWrapper);

        //为每个专业查询对应的departmentName和categoryName
        List<MajorDto> majorDtoList = majorList.stream().map(item -> {
            MajorDto majorDto = new MajorDto();
            //对象复制
            BeanUtil.copyProperties(item,majorDto);
            majorDto.setDepartmentName(departmentService.getById(item.getDepartmentId()).getName());
            majorDto.setCategoryName(categoryService.getById(item.getCategoryId()).getName());
            return majorDto;
        }).collect(Collectors.toList());

        //转存到redis
        redisUtil.set(majorCategoryKey+categoryId,JSONUtil.toJsonStr(majorDtoList), Constants.EXPIRE_WEEK);

        return majorDtoList;
    }

    /**
     * 专业展示页（未测试mbti）
     * 1.默认分类是学硕
     * 2.默认学科是经济学
     * @return
     */
    @Override
    public List<Major> selectMajorWithCategoryAndDepartment(String categoryId, String departmentId) {
        //构造查询构造器
        LambdaQueryWrapper<Major> majorLambdaQueryWrapper = new LambdaQueryWrapper<>();
        majorLambdaQueryWrapper.eq(Major::getCategoryId,categoryId);
        majorLambdaQueryWrapper.eq(Major::getDepartmentId,departmentId);

        //查询符合条件的专业
        List<Major> majorList = this.list(majorLambdaQueryWrapper);

        return majorList;
    }

    /**
     * 查询专业名称
     * redis做缓存
     * @return
     */
    @Override
    public List<Major> queryList() {
        List<Major> majorList;
        //根据key查询redis中是否缓存了数据
        String jsonStr = (String) redisUtil.get(majorKey);
        if (StrUtil.isNotBlank(jsonStr)){
            //不为空，redis中有改key的数据，直接转成对象返回
            majorList = JSONUtil.toBean(jsonStr, new TypeReference<List<Major>>() {
            }, true);
            return majorList;
        }
        majorList = this.list();
        redisUtil.set(majorKey,JSONUtil.toJsonStr(majorList),604800);
        return majorList;
    }
}
